#include <stdio.h>
#include <stdlib.h>

enum bool{false,true};

struct Point {
  double x,y,z;
};

struct Triangle {
  struct Point v[3];
};

struct Vertex {
  struct Point *v;
  int nadjacent;
  struct Point **adjacent;
};

struct Vertex1 {
  struct Point *v;
  int npredessors;
  int nroommates;
  int nsuccessors;
  struct Point *predessors;
  struct Point *roommates;
  struct Point *successors;
};

struct Triangle *ReadInput(const char *file_name, int *numof_triangles) {
  FILE *SurfaceFile;
  struct Triangle *input;
  int i,j;

  SurfaceFile = fopen(file_name,"r");
  fscanf(SurfaceFile,"%d",numof_triangles);
  input = (struct Triangle *)malloc(*numof_triangles*sizeof(struct Triangle));

  for(i=0;i<*numof_triangles;++i) {
    for(j=0;j<3;++j) {
      fscanf(SurfaceFile,"%le %le %le",&(input[i].v[j].x),&(input[i].v[j].y),&(input[i].v[j].z));
    }
  }
  return input;
}

enum bool ArePointsEqual(struct Point *a,struct Point *b) {
  return (a->x == b->x && a->y == b->y && a->z == b->z) ? true:false;
}

struct Point **GetPointArray(struct Triangle *polyhedron, int numof_triangles,
                            int *numof_points) {
  struct Point **point_array;
  int i,j,k,temp=0;

  point_array = (struct Point **)malloc(3*numof_triangles*sizeof(struct Point *));
  for(i=0;i<3*numof_triangles;++i) 
    point_array[i] = (struct Point *)malloc(sizeof(struct Point));

  *numof_points = 0;
  for(i=0;i<numof_triangles;++i) {
    for(k=0;k<3;++k) {
      for(j=0;j<i;++j) 
        if(ArePointsEqual(&(polyhedron[i].v[k]),point_array[j]) == true) {
          printf("%d %d %d\n",i,k,numof_triangles);
          temp = 1;
          break; 
        }
      if(temp != 1) point_array[(*numof_points)++] = &(polyhedron[i].v[k]);
        else temp = 0;
    }
  }
  point_array =  (struct Point **)realloc(point_array,
                      (*numof_points)*sizeof(struct Point *));
  return point_array;
}

struct Vertex *BuildPolyhedronGraph(struct Triangle *input, int numof_triangles,
                               struct Point **point_array, int numof_points) {
  struct Vertex *result;
  int i,j,k,temp;
  
  result = (struct Vertex *)malloc(numof_points*sizeof(struct Vertex));
  
  temp = -1;
  for(i=0;i<numof_points;++i) {
    result[i].adjacent = (struct Point **)malloc(numof_points*sizeof(struct Point *));
    result[i].v = point_array[i];
    result[i].nadjacent = 0;
    for(j=0;j<numof_triangles;++j)
      for(k=0;k<3;++k) {
        printf("%d %d %d\n",i,j,k);
        if(ArePointsEqual(point_array[i],&(input[j].v[k])) == true) {
          temp = k;
          //printf("%d %d\n",j,temp);
          break;
        }
      }
      //printf("%d %d %d\n",i,j,temp);
      if (temp != -1) {
        for(k=0;k<3;++k) 
          if(k!=temp) {
            //printf("-- %d %d\n",j,temp);
            result[i].adjacent[result[i].nadjacent++] = &(input[j].v[k]);
          }
        temp = -1;
      }
    result[i].adjacent = (struct Point **)realloc(result[i].adjacent,
                    result[i].nadjacent*sizeof(struct Point *));
  }
  return result;
}

void PrintPolyhedronGraph(struct Vertex *polyhedron,int numof_vertexes) {
  int i,j;

  for(i=0;i<numof_vertexes;++i) {
    printf("%d:\n",i);
    for(j=0;j<polyhedron[i].nadjacent;++j)
      printf("\t%le %le %le\n",polyhedron[i].adjacent[j]->x,
        polyhedron[i].adjacent[j]->y,polyhedron[i].adjacent[j]->z);
    printf("\n\n");
  }
}

int main() {
  FILE *SurfaceFile;
  struct Triangle *input;
  struct Point **parray;
  struct Vertex *Graph;
  double x;
  int numof_triangles,numof_points,i,j;
  
  input = ReadInput("data",&numof_triangles);

  for(i=0;i<numof_triangles;++i) {
    for(j=0;j<3;++j) {
      printf("%le %le %le\n",input[i].v[j].x,input[i].v[j].y,input[i].v[j].z);
    }
  }
  printf("\n\n");
  parray = GetPointArray(input,numof_triangles,&numof_points);
  for(i=0;i<numof_points;++i) printf("%le %le %le\n", 
    parray[i]->x,parray[i]->y,parray[i]->z);

  Graph = BuildPolyhedronGraph(input,numof_triangles,parray,numof_points);
  PrintPolyhedronGraph(Graph,numof_points);
 
  return 0;
}
